// 1. 安装vue-router    命令: npm install vue-router@4

// 2. 导入需要用到的函数   createRouter  createWebHistory
import { createRouter, createWebHistory } from "vue-router";
import type { RouteRecordRaw } from "vue-router";
import { App } from "vue";
import { useUserStore } from "@/store/userStore";
import * as http from "@/request/http";
import { ElMessage } from "element-plus";

// 3. 创建 路由表 routes
const routes: RouteRecordRaw[] = [
  // login 登陆页面
  {
    path: "/login",
    name: "login",
    component: () => import("@/pages/login/index.vue"),
  },
  // 动态添加路由 否则 没有相应权限的用户 如果知道路径 也可以手动访问到相应的内容
];

// 4. 创建 路由实例 router
const router = createRouter({
  routes,
  history: createWebHistory(),
});

// 全局路由导航守卫 beforeEach
router.beforeEach(async (to, form, next) => {
  // console.log('进入了全局路由导航守卫 beforeEach', to.fullPath);
  const userStore = useUserStore();
  const token = localStorage.getItem("token");
  // 问题1 : 因为当前用户信息请求回来是需要经过pinia里面的getters来处理的,如果当前用户刷新时,会导致数据为空的问题
  // 解决1 : (已登陆状态 token ,并且pinia菜单数据为空的话),需要重新 请求用户信息,更新pinia数据
  if (token && userStore.menus.length == 0) {
    let adminData = await http.admin.adminInfo();
    if (adminData.code === 200) {
      userStore.updateMenus(adminData.data.menus);
      userStore.userName = adminData.data.username;
      // 根据处理好之后的新菜单,动态添加 一级路由配置 和 二级路由配置
      const menuRoutes = userStore.getMenuRoutes;
      for (let k in menuRoutes) {
        // 一级路由对象
        let routeObj: RouteRecordRaw = {
          path: "/" + menuRoutes[k].name,
          name: menuRoutes[k].name,
          component: () => import("@/pages/home/index.vue"),
          children: [],
        };
        // 处理 二级路由
        menuRoutes[k].children?.forEach((item) => {
          routeObj.children?.push({
            path: item.name,
            name: item.name,
            component: () =>
              import(`@/pages/${menuRoutes[k].name}/${item.name}.vue`),
            // 存储面包屑需要用到的数据
            meta: {
              targetRoutePath: "/" + menuRoutes[k].name, // 一级路由路径
              targetRouteName: menuRoutes[k].title, // 一级路由的中文名称
              targetSubRouteName: item.title, // 二级路由的中文名称
            },
          });
        });
        // 添加重定向
        // 如果当前的一级路由存在二级路由的情况下,默认设置一个 重定向 重定向到第一个二级路由的路径
        if (routeObj.children.length != 0) {
          // 这里用到的 ! 是 ts中的非空断言  (undefined null)  告诉ts  我可以确定这里不是空的 相信我
          routeObj.redirect =
            "/" + menuRoutes[k].name + "/" + menuRoutes[k].children![0].name;
        }

        // 动态添加到router中
        router.addRoute(routeObj);
      }

      // 动态添加首页路由
      router.addRoute({
        path: '/',
        name: 'home',
        redirect: '/index',
        component: () => import('@/pages/home/index.vue'),
        children: [
          { path: "index", component: () => import("@/pages/index/index.vue") },
        ],
      });
      // console.log("fullPath : ", to.fullPath);
      // next(); // 如果是动态添加的路由,刷新页面就空白了,需要手动告诉router去哪里;
      next(to.fullPath);
      // await router.isReady(); // 等待路由器初始化完成
      // next();
    } else {
      // 请求失败
      console.log("beforeEach 中 请求用户信息失败了........");
      // 问题2 : token失效 (手动修改token值,模拟token失效)  这样再次刷新,请求时提示token已过期/已失效
      // 解决2 : 删除token 并且跳转回到登陆页面,让用户重新登陆
      localStorage.removeItem("token");
      next("/login");
    }
  } else if (!token && to.fullPath != "/login") {
    // 当前无 token 时, 引导用户去登陆页面  登陆
    next("/login");
  } else if (token && to.fullPath == "/login" && userStore.menus.length != 0) {
    // 如果已经登陆,不允许手动的回到登陆页面, (因为如果此时手动回去,所有的权限依旧是之前用户的)
    // 此时应该 让它从哪里来回哪里去

    ElMessage.warning("你已登陆,请退出登陆再重试!"); // 提示一下用户
    next(form.fullPath);
  } else {
    // next()  必须写   必须放行  否则组件渲染不出来,页面空白
    // next('/index')  // Error  这样写会导致  导航无限制的重定向
    next();
  }
});

// 导出 router 路由对象
// 下面是暴露一个 初始化路由的方法  因为common里面的退出登陆功能需要用到router进行跳转,所以这里也导出router供它使用
export default router;

// 5. 暴露一个  初始化路由方法(相当于以前的 导出路由对象router)
export function initRouter(app: App<Element>) {
  app.use(router);
}
